package com.lagou.client.handler;

import com.lagou.client.util.ZkClientUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @author Kirito
 * @description: 负载均衡器
 * @date 2020/06/04
 */
public class LoadBalanceHandler {

    private List<String> servers;

    public LoadBalanceHandler(List<String> servers) {
        this.servers = servers;
    }

    public String choose() {

        if (servers == null || servers.size() == 0) {
            throw new RuntimeException("There is no available server...");
        }

        List<String> availableServers = new ArrayList<>();
        Map<String, Long> responseMap = new HashMap<>();
        for (String server : servers) {
            Object time = ZkClientUtil.getResponse(server);
            if (time == null) {
                // 首次请求
                availableServers.add(server);
            } else {
                long response = Long.parseLong(ZkClientUtil.getResponse(server).toString());
                System.out.println("Response time of " + server + " is: " + response);
                responseMap.put(server, response);
            }
        }

        String server = "";
        if (availableServers.size() == 0) {
            // 获取map的最小响应时间
            Long minValue = getMapMinValue(responseMap);
            // 找到响应时间最小的server，可能不止一个
            for (Map.Entry<String, Long> entry : responseMap.entrySet()) {
                if (entry.getValue() == minValue) {
                    availableServers.add(entry.getKey());
                }
            }

            // 判断找到几个可用服务
            if (availableServers.size() == 1) {
                // 如果只有一个直接返回
                server = availableServers.get(0);
            } else {
                // 如果又多个，随机挑选一个返回
                Random r = new Random();
                int index = r.nextInt(availableServers.size());
                server = availableServers.get(index);
            }
        } else {
            // 如果又多个，随机挑选一个返回
            Random r = new Random();
            int index = r.nextInt(availableServers.size());
            server = availableServers.get(index);
        }

        System.out.println("Available server address is: " + server);
        return server;
    }

    private Long getMapMinValue(Map<String, Long> map) {
        List<Map.Entry<String, Long>> list = new ArrayList(map.entrySet());
        Collections.sort(list, (o1, o2) -> (o1.getValue().intValue() - o2.getValue().intValue()));
        return list.get(0).getValue();
    }
}
